/*
 * Copyright (c) [2019] [zr]
 *    [bsf] is licensed under the Mulan PSL v1.
 *    You can use this software according to the terms and conditions of the Mulan PSL v1.
 *    You may obtain a copy of Mulan PSL v1 at:
 *       http://license.coscl.org.cn/MulanPSL
 *    THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 *    IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 *    PURPOSE.
 *
 *    See the Mulan PSL v1 for more details.
 */

package bsf

import (
	"fmt"
	"gitee.com/zr233/bsf/errors"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"path"
	"strconv"
)

var controllerBaseExcludeMethods = map[string]bool{
	"Ctx":            true,
	"FromFile":       true,
	"PostFromInt":    true,
	"PostFromIntPtr": true,
}

type Controller interface {
	isController() bool
}

type ControllerBase struct {
	ctx *gin.Context
}

func newControllerBase(ctx *gin.Context) *ControllerBase {
	return &ControllerBase{ctx: ctx}
}

func (c *ControllerBase) isController() bool {
	return true
}
func (c *ControllerBase) Ctx() *gin.Context {
	return c.ctx
}

type File struct {
	Ext  string
	Data []byte
}

func (c *ControllerBase) FromFile(key string) (f *File) {
	defer func() {
		if p := recover(); p != nil {
			panic(fmt.Errorf("key %s:\n%w", key, p.(error)))
		}
	}()

	header, err := c.Ctx().FormFile(key)
	if err != nil {
		err = errors.NewParamErr(err)
		panic(err)
	}
	gFile, err := header.Open()
	if err != nil {
		err = errors.NewParamErr(err)
		panic(err)
	}
	defer func() {
		_ = gFile.Close()
	}()
	f = &File{}
	f.Ext = path.Ext(header.Filename)
	f.Data, err = ioutil.ReadAll(gFile)
	if err != nil {
		err = errors.NewParamErr(err)
		panic(err)
	}
	return
}

func (c *ControllerBase) PostFromInt(key string) (value int) {
	valueStr := c.Ctx().PostForm(key)
	value, err := strconv.Atoi(valueStr)
	if err != nil {
		err = errors.NewParamErr(fmt.Errorf("key %s, value %s:\n%w", key, valueStr, err))
		panic(err)
	}
	return
}
func (c *ControllerBase) PostFromIntPtr(key string) (ptr *int) {
	valueStr := c.Ctx().PostForm(key)
	if valueStr == "" {
		return
	}

	value, err := strconv.Atoi(valueStr)
	if err != nil {
		err = errors.NewParamErr(fmt.Errorf("key %s, value %s:\n%w", key, valueStr, err))
		panic(err)
	}
	ptr = &value
	return
}
